/**
 * \文件 lwrb.h
 * \brief LwRB - 轻量级环形缓冲器
 */

/*
 * 版权所有 （c） 2024 Tilen MAJERLE
 *
 * 特此免费向任何人授予许可
 * 获取本软件和相关文档的副本
 * 文件（“软件”），不受限制地处理软件，
 * 包括但不限于使用、复制、修改、合并、
 * 发布、分发、再许可和/或出售本软件的副本，
 * 并允许接受本软件的人这样做，
 * 受以下条件限制：
 *
 * 上述版权声明和本许可声明应为
 * 包含在软件的所有副本或大部分中。
 *
 * 本软件按“原样”提供，不提供任何形式的保证，
 * 明示或暗示，包括但不限于保证
 * 适销性、特定用途的适用性
 * 和不侵权。在任何情况下，作者或版权均不得
* 持有人对任何索赔、损害赔偿或其他责任负责，
 * 无论是在合同、侵权或其他诉讼中产生的
 * 来自、退出或与软件有关或使用或
 * 软件中的其他交易。
 *
 * 此文件是 LwRB - 轻量级环形缓冲区库的一部分。
 *
 * 作者：Tilen MAJERLE <tilen@majerle.eu>
 * 版本： v3.0.0-rc1
 */
#ifndef LWRB_HDR_H
#define LWRB_HDR_H

#include <stdint.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
 * \defgroup        LWRB Lightweight ring buffer manager
 * \brief           Lightweight ring buffer manager
 * \{
 */

// #ifdef LWRB_DISABLE_ATOMIC
// typedef unsigned long lwrb_ulong_t;
// #else
// #include <stdatomic.h>
// typedef atomic_ulong lwrb_ulong_t;
// #endif


// /* 强制禁用原子操作，适配 ARMCC 5.x */
// #define LWRB_DISABLE_ATOMIC
// typedef volatile unsigned long lwrb_ulong_t;



#ifndef LWRB_DISABLE_ATOMIC
#define LWRB_DISABLE_ATOMIC
#endif
typedef volatile unsigned long lwrb_ulong_t;

/**
 * \brief           Event type for buffer operations
 */
typedef enum {
    LWRB_EVT_READ,  /*!< Read event */
    LWRB_EVT_WRITE, /*!< Write event */
    LWRB_EVT_RESET, /*!< Reset event */
} lwrb_evt_type_t;

/**
 * \brief           Buffer structure forward declaration
 */
struct lwrb;

/**
 * \brief           Event callback function type
 * \param[in]       buff: Buffer handle for event
 * \param[in]       evt: Event type
 * \param[in]       bp: Number of bytes written or read (when used), depends on event type
 */
typedef void (*lwrb_evt_fn)(struct lwrb* buff, lwrb_evt_type_t evt, size_t bp);

/**
 * \brief           Buffer structure
 */
typedef struct lwrb {
    uint8_t* buff;  /*!< Pointer to buffer data. Buffer is considered initialized when `buff != NULL` and `size > 0` */
    size_t size;    /*!< Size of buffer data. Size of actual buffer is `1` byte less than value holds */
    lwrb_ulong_t r; /*!< Next read pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */
    lwrb_ulong_t w; /*!< Next write pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */
    lwrb_evt_fn evt_fn; /*!< Pointer to event callback function */
} lwrb_t;

uint8_t lwrb_init(lwrb_t* buff, void* buffdata, size_t size);
uint8_t lwrb_is_ready(lwrb_t* buff);
void lwrb_free(lwrb_t* buff);
void lwrb_reset(lwrb_t* buff);
void lwrb_set_evt_fn(lwrb_t* buff, lwrb_evt_fn fn);

/* Read/Write functions */
size_t lwrb_write(lwrb_t* buff, const void* data, size_t btw);
size_t lwrb_read(lwrb_t* buff, void* data, size_t btr);
size_t lwrb_peek(const lwrb_t* buff, size_t skip_count, void* data, size_t btp);

/* Buffer size information */
size_t lwrb_get_free(const lwrb_t* buff);
size_t lwrb_get_full(const lwrb_t* buff);

/* Read data block management */
void* lwrb_get_linear_block_read_address(const lwrb_t* buff);
size_t lwrb_get_linear_block_read_length(const lwrb_t* buff);
size_t lwrb_skip(lwrb_t* buff, size_t len);

/* Write data block management */
void* lwrb_get_linear_block_write_address(const lwrb_t* buff);
size_t lwrb_get_linear_block_write_length(const lwrb_t* buff);
size_t lwrb_advance(lwrb_t* buff, size_t len);

/* Search in buffer */
uint8_t lwrb_find(const lwrb_t* buff, const void* bts, size_t len, size_t start_offset, size_t* found_idx);

/**
 * \}
 */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* LWRB_HDR_H */
